package com.gmadmin.controller.auth;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONUtil;
import com.gmadmin.common.ApiResponse;
import com.gmadmin.common.HttpStatus;
import com.gmadmin.controller.auth.config.LoginCodeEnum;
import com.gmadmin.controller.auth.config.LoginProperties;
import com.gmadmin.exception.UserException;
import com.gmadmin.payload.auth.LoginRequest;
import com.gmadmin.utils.RedisUtils;
import com.gmadmin.utils.jwt.JwtUtil;
import com.gmadmin.entity.vo.auth.JwtResponse;
import com.wf.captcha.base.Captcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangliang
 * @version 1.0
 * @date 2021/12/13 13:32
 */
@Api(value = "登录验证", tags = "系统验证")
@RestController
@RequestMapping("/api/system/auth")
public class AuthController {

    protected static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    private final AuthenticationManager authenticationManager;

    private final JwtUtil jwtUtil;

    private final LoginProperties loginProperties;

    private final RedisUtils redisUtils;


    public AuthController(AuthenticationManager authenticationManager, JwtUtil jwtUtil, LoginProperties loginProperties, RedisUtils redisUtils) {
        this.authenticationManager = authenticationManager;
        this.jwtUtil = jwtUtil;
        this.loginProperties = loginProperties;
        this.redisUtils = redisUtils;
    }

    @ApiOperation(value = "登录")
    @PostMapping("/login")
    public ApiResponse<JwtResponse> login(@RequestBody LoginRequest loginRequest) {
        logger.debug("登录信息:{}", JSONUtil.toJsonStr(loginRequest));
        // 查询验证码
        String verificationCode;
        verificationCode = (String) redisUtils.get(loginRequest.getUuid());
        if (CharSequenceUtil.isBlank(verificationCode)) {
            throw new UserException(HttpStatus.CODE_HAS_EXPIRED);
        }
        if (CharSequenceUtil.isBlank(loginRequest.getVerificationCode()) || !loginRequest.getVerificationCode().equalsIgnoreCase(verificationCode)) {
            throw new UserException(HttpStatus.CODE_HAS_ERROR);
        }
        // 清除验证码
        redisUtils.del(loginRequest.getUuid());

        Authentication authentication;
        authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsernameOrPhone(), loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);

        JwtResponse jwtResponse = jwtUtil.createJWT(authentication, loginRequest.getRememberMe());


        logger.debug("登录成功: {}", jwtResponse);
        return ApiResponse.ofSuccess(jwtResponse);
    }


    @ApiOperation("退出")
    @DeleteMapping("/logout")
    public ApiResponse<HttpStatus> logout() {
        return new ApiResponse<HttpStatus>().ofStatus(HttpStatus.OK);
    }

    @ApiOperation("获取验证码")
    @GetMapping("/code")
    public ApiResponse<Map<String, Object>> getCodeImage() {
        Captcha captcha = loginProperties.getCaptcha();
        String uuid = IdUtil.simpleUUID();

        //当验证码类型为 arithmetic时且长度 >= 2 时，captcha.text()的结果有几率为浮点型
        String captchaValue = captcha.text();
        String dian = ".";
        if (captcha.getCharType() - 1 == LoginCodeEnum.arithmetic.ordinal() && captchaValue.contains(dian)) {
            captchaValue = captchaValue.split("\\.")[0];
        }
        // 保存

        redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
        // 验证码信息
        Map<String, Object> imgResult = Map.of("img", captcha.toBase64(), "uuid", uuid);
        return ApiResponse.ofSuccess(imgResult);
    }

}
